#!/usr/bin/python
# -*- coding: UTF-8 -*-

import os
import shutil
import json
import platform
import sys
import subprocess
import glob
from driver import Initializer
from driver import Builder
from util import *
from option import Options

class Initializer_csharp(Initializer):
    def __init__(self, options):
        self.options = options

    def check(self):
        # 如果没有初始化frontend 就在这里进行初始化
        if not os.path.exists("repo.init.csharp"):
            return self.init()
        else:
            return True
        
    def build_backend(self):
        pass
        
    def init(self):
        if not Initializer.checkPrecondition(self):
            return False

        # 生成必要的路径
        if not os.path.exists("src/idl"):
            os.makedirs("src/idl")

        # 检查rpc-frontend环境是否齐全
        frontend = "rpc-frontend"
        if platform.system() == "Windows":
            frontend += ".exe"

        if not os.path.exists('./bin/' + frontend):
            check_frontend(self)

        os.chdir("tmp")
        if os.path.exists('rpc-backend-csharp'):
            os.chdir("rpc-backend-csharp")
            os.system('git pull origin')
            os.chdir('..')
        else:
            if os.system("git clone https://gitee.com/dennis-kk/rpc-backend-csharp") != 0:
                print("git clone https://gitee.com/dennis-kk/rpc-backend-csharp failed")
                return False    

        if not os.path.exists("../bin"):
            os.mkdir("../bin")
            
        shutil.copyfile("rpc-backend-csharp/rpc/tools/csharpgen.py", "../bin/csharpgen.py")
        shutil.copyfile("rpc-backend-csharp/rpc/tools/csharpgen_pb_layer.py", "../bin/csharpgen_pb_layer.py")
        if not os.path.exists('../usr/csharp/rpc_framework'):
            os.makedirs('../usr/csharp/rpc_framework')
        if not os.path.exists('../usr/csharp/rpc_framework/rpc'):
            os.makedirs('../usr/csharp/rpc_framework/rpc')
        shutil.copytree('rpc-backend-csharp/Lib', '../usr/csharp/rpc_framework/Lib')
        shutil.copytree('rpc-backend-csharp/rpc/buffer', '../usr/csharp/rpc_framework/buffer')
        shutil.copytree('rpc-backend-csharp/rpc/pool', '../usr/csharp/rpc_framework/pool')
        shutil.copytree('rpc-backend-csharp/rpc/rpc', '../usr/csharp/rpc_framework/base')
        shutil.copytree('rpc-backend-csharp/rpc/socket', '../usr/csharp/rpc_framework/socket')
        os.chdir("..")
        open("repo.init.csharp", "w").close()
        if not os.path.exists('usr/csharp'):
            os.makedirs('usr/csharp')
        return True
        
    def checkEnv(self):
        os.system("protoc --version")
        os.system("git --version")
        os.system("cmake --version")
        if platform.system() == "Linux":
            if os.system("gcc --version") != 0:
                os.system("clang --version")
        else:
            print("Visual Studio 16 2019")

class Builder_csharp(Builder):
    def __init__(self, options):
        Builder.__init__(self, options)

    def build_idl(self, name, sname = None):
        pass
        
    def files(self, curr_dir = '.', ext = '*.exe'):
        for i in glob.glob(os.path.join(curr_dir, ext)):
            yield i

    def all_files(self, rootdir, ext):
        for name in os.listdir(rootdir):
            if os.path.isdir(os.path.join(rootdir, name)):
                try:
                    for i in all_files(os.path.join(rootdir, name), ext):
                        yield i
                except:
                    pass
        for i in files(rootdir, ext):
            yield i

    def remove_files(self, rootdir, ext, show = False):
        for i in files(rootdir, ext):
            if show:
                print(i)
            os.remove(i)

    def addIdl2Repo(self, file_name, sname = None, add=True):
        if not add:
            file_name = "src/idl/" + file_name
        if not os.path.exists(file_name):
            print(file_name + " not found")
            return
        file_name = self.check_idl_name(file_name)

        # 递归处理idl import 依赖文件
        idl_list = deal_idl_import(file_name)
        # 递归拷贝所有idl依赖文件
        # 拷贝idl并生成对应的文件和文件夹 src/idl 目录下 保持原有目录一致
        if add:
            copy_dep_idl(os.path.dirname(file_name), idl_list, 'src/idl')
            shutil.copyfile(file_name, './src/idl/' + os.path.basename(file_name))
        

        os.chdir("src/idl/")
        cmd = subprocess.Popen(["../../bin/rpc-frontend", "-t", "csharp", "-f", os.path.basename(file_name)], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        ret = cmd.communicate()
        if cmd.returncode != 0:
            print(ret[1])
            return
        cmd = subprocess.Popen(["../../bin/rpc-frontend", "-t", "protobuf", "-f", os.path.basename(file_name)], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        ret = cmd.communicate()
        if cmd.returncode != 0:
            print(ret[1])
            return
        (base_name, _) = os.path.splitext(os.path.basename(file_name))
        cmd = subprocess.Popen(["python", "../../bin/csharpgen.py", base_name+'.idl.csharp.json'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        cmd.communicate()
        if cmd.returncode != 0:
            print("csharpgen.py failed")
            print(ret[1])
            return
        cmd = subprocess.Popen(["python", "../../bin/csharpgen_pb_layer.py", base_name+'.idl.csharp.json', base_name+'.idl.protobuf.json'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        cmd.communicate()
        if cmd.returncode != 0:
            print("csharpgen_pb_layer.py failed")
            print(ret[1])
            return
        json_str = json.load(open(base_name + ".idl.csharp.json"))

        if not os.path.exists('../../usr/csharp/'+base_name):
            os.makedirs('../../usr/csharp/'+base_name)
        shutil.copyfile('rpc.register.cs', '../../usr/csharp/rpc.register.cs')
        shutil.copyfile(base_name+'.service.cs', '../../usr/csharp/'+base_name+'/'+base_name+'.service.cs')
        shutil.copyfile(base_name.capitalize()+'.service.cs', '../../usr/csharp/'+base_name+'/'+base_name.capitalize()+'.service.cs')
        shutil.copyfile(base_name+'.service.protobuf.serializer.cs', '../../usr/csharp/'+base_name+'/'+base_name+'.service.protobuf.serializer.cs')

        if json_has_attr(json_str, "structNames"):
            for struct_name in json_str["structNames"]:
                if os.path.exists(struct_name+".struct.cs"):
                    shutil.copyfile(struct_name+".struct.cs", "../../usr/csharp/"+ struct_name + ".struct.cs")
                    shutil.copyfile(struct_name+".struct.impl.cs", "../../usr/csharp/"+ struct_name + ".struct.impl.cs")
                    shutil.copyfile(struct_name+"Struct.cs", "../../usr/csharp/"+ struct_name + "Struct.cs")

        if json_has_attr(json_str, "enumNames"):
            for enum_name in json_str["enumNames"]:
                if os.path.exists(enum_name+".enum.cs"):
                    shutil.copyfile(enum_name+".enum.cs", "../../usr/csharp/"+ enum_name+".enum.cs")
                    shutil.copyfile(enum_name + "Enum.cs", "../../usr/csharp/" + enum_name + "Enum.cs")
        
        if os.path.exists(base_name.capitalize()+"Service.cs"):
            shutil.copyfile(base_name.capitalize()+"Service.cs", "../../usr/csharp/"+base_name+'/'+ base_name.capitalize()+"Service.cs")

        if ("services" in json_str) and (json_str["services"] is not None):
            for service in json_str['services']:
                if not os.path.exists('../../usr/csharp/'+base_name+'/'+service['name']):
                    os.makedirs('../../usr/csharp/'+base_name+'/'+service['name'])
                stub_file_name = '../../usr/csharp/'+base_name+'/'+service['name']+'/'+base_name+'.service.'+service['name']+'.impl.cs'
                inter_file_name = '../../usr/csharp/'+base_name+'/'+service['name']+'/'+base_name+'.service.'+service['name']+'.cs'
                if not os.path.exists(stub_file_name) and os.path.exists(base_name+'.service.'+service['name']+'.impl.cs'):
                    shutil.copyfile(base_name+'.service.'+service['name']+'.impl.cs', stub_file_name)
                if os.path.exists(base_name+'.service.'+service['name']+'.cs'):
                    shutil.copyfile(base_name+'.service.'+service['name']+'.cs', inter_file_name)

        if not os.path.exists('csharp_'+base_name):
            os.makedirs('csharp_'+base_name)
        for file in glob.glob(r'./*.cs'):
            shutil.copyfile(file, os.path.join('csharp_'+base_name, file))
        self.remove_files('.', '*.cs')
        self.remove_files('.', "*.proto")
        # 多个idl 可能需要同时注册 拷贝回去 做第二次准备
        shutil.copyfile('../../usr/csharp/rpc.register.cs', 'rpc.register.cs')
        os.chdir("../../")
        
    def updateRoot(self):
        initializer = Initializer_csharp(Options())
        os.chdir("tmp/rpc-frontend/")
        os.system('git pull origin')
        os.chdir("..")
        initializer.build_frontend()
        os.chdir("..")
        os.chdir("tmp/rpc-backend-csharp/")
        os.system('git pull origin')
        shutil.copyfile("rpc/tools/csharpgen.py", "../../bin/csharpgen.py")
        shutil.copyfile("rpc/tools/csharpgen_pb_layer.py", "../../bin/csharpgen_pb_layer.py")
        os.chdir("..")
        initializer.build_backend()
        os.chdir("../../")